home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
bildschirmschoner
/
snowblank
/
source
/
xsnow
/
blank.c
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
13KB
|
505 lines
/* --------------------------------------------------------------------
*
* A christmas blanker inspired by xsnow
*
* This is an advanced but slower version compared to snow
*
* initialization/cleanup code copied from the dragon module
* (dragon module: (C)Alexander Kneer and Michael D. Bayne)
*
* -------------------------------------------------------------------- */
#include <exec/memory.h>
#include <math.h>
#include <stdlib.h>
#include "/includes.h"
#define STAGES 2 /* Number of different shapes */
#define BLANKDELAY 100 /* This many snowflakes are displayed before
* we check if to continue blanking */
#define COUNTLIMIT 6 /* max. number of moves in one direction */
#define COUNTMIN 1 /* min. number of moves in one direction */
/* random generation function macros */
#define COUNTFUNC RangeRand(COUNTLIMIT-COUNTMIN)+COUNTMIN
#define DXFUNC RangeRand(5)-2;
#define DYFUNC RangeRand(2)+1;
typedef enum { false, true, random } bool;
bool BIGFLAKES;
int NUMSNOW;
bool COLLECT;
bool SHOWSTARS;
bool SHOWSNOWMEN;
bool SHOWTREES;
bool SHOWBG;
int NUMOBJ;
int patx[10] = { -1,-1, 1, 1, 0 , -1, 1, 0, 0, 0 };
int paty[10] = { -1, 1,-1, 1, 0 , 0, 0, 1,-1, 0 };
int *collect;
int *starx;
int *stary;
int starnum;
typedef struct
{ int x,y; /* The current coordinates */
int dx,dy; /* Movement direction is (dx,dy) */
int count; /* How long to keep direction dx */
int stage; /* STAGES different shapes */
short int mem[5]; /* stores the pixels below its shape */
} snowflake;
/* Color pens */
#define CBLACK 0
#define CWHITE 1
#define CGREEN 2
#define CBROWN 3
#define CDGREY 5
#define CMGREY 6
#define CLGREY 7
#define CYELLOW 4
Triplet *ColorTable = 0L;
#define PR_FLAKE 0
#define PR_BIG 2
#define PR_COLLECT 3
#define PR_STARS 5
#define PR_BG 6
#define PR_SNMAN 8
#define PR_TREE 9
#define PR_OBJ 11
#define PR_MODE 13
VOID Defaults( PrefObject *Prefs )
{
Prefs[PR_FLAKE].po_Level = 200;
Prefs[PR_BIG].po_Level = 1;
Prefs[PR_COLLECT].po_Level = 1;
Prefs[PR_STARS].po_Level = 1;
Prefs[PR_BG].po_Level = 1;
Prefs[PR_SNMAN].po_Level = 1;
Prefs[PR_OBJ].po_Level = 20;
Prefs[PR_TREE].po_Level = 1;
Prefs[PR_MODE].po_ModeID = getTopScreenMode();
}
/* Remove a single snowflake's image from the screen */
__inline void undraw(snowflake *flake, struct RastPort *rp)
{
if (BIGFLAKES)
{
int *startx = patx + 5*(flake->stage);
int *starty = paty + 5*(flake->stage);
int i;
for (i=0; i<5; i++)
{ if (flake->mem[i] != -1)
{ SetAPen(rp,flake->mem[i]);
WritePixel(rp,flake->x+(*startx),flake->y+(*starty));
}
startx++;
starty++;
}
}
else
{ if (flake->mem[0] != -1)
{ SetAPen(rp,flake->mem[0]);
WritePixel(rp,flake->x,flake->y);
}
}
}
__inline void WriteLine(struct RastPort *rp, int width, int height, int x, int y, int scale,
int x1, int y1, int x2, int y2)
{ x1=x1*4*scale; y1=y1*4*scale; x2=x2*4*scale; y2=y2*4*scale;
/* all coordinates are now 1.000 times too big */
Move(rp,x+x1/1000,y+y1/1000);
Draw(rp,x+x2/1000,y+y2/1000);
}
void draw_tree(struct RastPort *rp, int width, int height)
{ int x,y;
int scale;
x = RangeRand(width-42);
y = RangeRand((height*3)/4-42)+height/4;
scale = (y*1000)/height;
SetAPen(rp,CBROWN);
WriteLine(rp,width,height,x,y,scale,4,10,6,10);
WriteLine(rp,width,height,x,y,scale,4,10,4,8);
WriteLine(rp,width,height,x,y,scale,6,10,6,8);
SetAPen(rp,CGREEN);
WriteLine(rp,width,height,x,y,scale,0,8,10,8);
WriteLine(rp,width,height,x,y,scale,0,8,3,6);
WriteLine(rp,width,height,x,y,scale,10,8,7,6);
WriteLine(rp,width,height,x,y,scale,3,6,1,6);
WriteLine(rp,width,height,x,y,scale,7,6,9,6);
WriteLine(rp,width,height,x,y,scale,1,6,3,4);
WriteLine(rp,width,height,x,y,scale,9,6,7,4);
WriteLine(rp,width,height,x,y,scale,3,4,2,4);
WriteLine(rp,width,height,x,y,scale,7,4,8,4);
WriteLine(rp,width,height,x,y,scale,2,4,4,2);
WriteLine(rp,width,height,x,y,scale,8,4,6,2);
WriteLine(rp,width,height,x,y,scale,4,2,3,2);
WriteLine(rp,width,height,x,y,scale,6,2,7,2);
WriteLine(rp,width,height,x,y,scale,3,2,5,0);
WriteLine(rp,width,height,x,y,scale,7,2,5,0);
}
__inline void WriteBall(struct RastPort *rp, int x, int y, int scale,
int x1, int y1, int r)
{ int i,j;
x1=x1*4*scale; y1=y1*4*scale; r=(r*4*scale)/1000;
/* all coordinates are now 1.000 times too big */
for (j=1; j<r; j++)
{ i=r+1-j;
SetAPen(rp,16-((i*8)/r));
DrawEllipse(rp,x+x1/1000,y+y1/1000,i,i);
}
}
void draw_snowman(struct RastPort *rp, int width, int height)
{ int x,y;
int scale;
x = RangeRand(width-42);
y = RangeRand((height*3)/4-42)+height/4;
scale = (y*1000)/height;
SetAPen(rp,CLGREY);
/*if (scale > 400) WriteLine(rp,width,height,x,y,scale,1,4,7,4);*/
WriteBall(rp,x,y,scale,4,7,3);
WriteBall(rp,x,y,scale,4,4,2);
WriteBall(rp,x,y,scale,4,2,1);
}
/* draw a winterly landscape with everything and more :) */
LONG draw_landscape(struct Screen *scr, int width, int height, struct RastPort *rp)
{ int numobj,i;
LONG flg_end;
/* first: the landscape */
{ if (SHOWBG)
{ int x,y;
int *hei = malloc(sizeof(int)*width);
hei[0]=0;
for (i=1; i<width; i++)
{ hei[i] = hei[i-1]+RangeRand(3)-1;
}
for (y=height/4; y<height; y++)
{ for (x=0; x<width; x++)
{ int val = ((y+hei[x]) * 100) / height;
val = val - val/8 + RangeRand(val/4);
if (val<0) val = 0;
val = (val * 8)/100;
if (val<0) val = 0;
if (val>7) val = 7;
if (!val) SetAPen(rp,0);
else SetAPen(rp,val+8);
WritePixel(rp,x,y);
}
for (i=1; i<width; i++)
{ if (!RangeRand(3)) hei[i] = hei[i]+RangeRand(3)-1;
}
flg_end = ContinueBlanking();
ScreenToFront(scr);
if (flg_end != OK)
{ free(hei); return flg_end; }
}
}
/* else leave the background black */
}
/* possibly stars */
if (SHOWSTARS)
{ int count = RangeRand(50)+50;
int i;
starx = malloc(count*sizeof(int));
stary = malloc(count*sizeof(int));
SetAPen(rp,CYELLOW);
for (i=0; i<count; i++)
{ int x,y;
do { x = RangeRand(width);
y = RangeRand(height/4);
} while (ReadPixel(rp,x,y) != CBLACK);
WritePixel(rp,x,y);
starx[i] = x;
stary[i] = y;
}
starnum = count;
}
/* Draw some objects */
numobj = RangeRand(NUMOBJ/2)+NUMOBJ/2;
for (i=0; i<numobj; i++)
{ switch(RangeRand(4))
{ case 0: case 1: case 2: if (SHOWTREES)
draw_tree(rp,width,height); break;
case 3: if (SHOWSNOWMEN)
draw_snowman(rp,width,height); break;
}
}
return OK;
}
/* Draw a single snowflake's image to the screen */
__inline void draw(snowflake *flake, struct RastPort *rp)
{
if (BIGFLAKES)
{
int *startx = patx + 5*(flake->stage);
int *starty = paty + 5*(flake->stage);
int i;
SetAPen(rp,1);
for (i=0; i<5; i++)
{ int xx = flake->x+(*startx);
int yy = flake->y+(*starty);
flake->mem[i] = ReadPixel(rp,xx,yy);
if (flake->mem[i] == CWHITE)
{ flake->mem[i] = -1;
}
else
WritePixel(rp,xx,yy);
startx++;
starty++;
}
}
else
{ flake->mem[0] = ReadPixel(rp,flake->x,flake->y);
if (flake->mem[0] == CWHITE)
{ flake->mem[0] = -1;
}
else
{ SetAPen(rp,1);
WritePixel(rp,flake->x,flake->y);
}
}
}
/* change the position of a snowflake. If it leaves [0..width]x[0..height],
* generate a new one with coordinates (<random>,0) */
__inline void update(snowflake *curr, int width, int height, struct RastPort *rp)
{ bool gen_new;
int oldx = curr->x;
if (curr->count > 0)
{ curr->y = curr->y + curr->dy;
if (curr->y >= height-1)
{ gen_new = true;
}
else
{ curr->x = curr->x + curr->dx;
if (curr->x < 1 || curr->x >= width-1)
{ gen_new = true;
}
else
{ gen_new = false;
(curr->count)--;
if (curr->count <= 0)
{ curr->dx = DXFUNC;
curr->count = COUNTFUNC;
}
if (curr->stage)
{ curr->stage--;
}
else
{ curr->stage = STAGES-1;
}
}
}
}
/* do we have to compute a new flake? */
if (gen_new)
{ if (collect && curr->y > height-3)
{ collect[oldx]--;
if (collect[oldx]<height-20)
{ collect[oldx]=height-20;
}
curr->x = oldx;
curr->y = collect[oldx];
draw(curr,rp);
}
curr->x = RangeRand(width-2)+1;
curr->y = 1;
curr->dx = DXFUNC;
curr->dy = DYFUNC;
curr->count = COUNTFUNC;
curr->stage = RangeRand(STAGES);
}
}
LONG snow(struct Screen *scr, SHORT width, SHORT height)
{
unsigned int i;
LONG flg_end;
snowflake *flake,*curr;
int blankcount;
bool firstpass = true;
struct RastPort *rp = &(scr->RastPort);
starx = NULL; stary = NULL;
/* first draw a winterly landscape */
flg_end = draw_landscape(scr,width,height,rp);
if (flg_end != OK)
{ if (starx) free(starx);
if (stary) free(stary);
return flg_end;
}
/* initialize the snow array */
flake = malloc(NUMSNOW*sizeof(snowflake));
curr = flake;
for (i=0; i<NUMSNOW; i++)
{ curr->x = RangeRand(width-2)+1;
curr->y = RangeRand(height-2)+1;
curr->dx = DXFUNC;
curr->dy = DYFUNC;
curr->count = COUNTFUNC;
curr->stage = RangeRand(STAGES);
curr++;
}
/* and the collect array */
if (COLLECT)
{ collect = malloc(sizeof(int)*width);
for (i=0; i<width; i++)
{ collect[i] = height-2;
}
collect[0] = 0;
collect[width-1] = 0;
}
else
{ collect = NULL;
}
/* Update all snowflakes forever. Update includes removal from the screen,
* computation of new position, drawing on the screen */
blankcount = BLANKDELAY;
while (1)
{ curr = flake;
{ if (SHOWSTARS)
{ int num = RangeRand(starnum);
int x = starx[num];
int y = stary[num];
int val = ReadPixel(rp,x,y);
if (val != CWHITE)
{ if (val == CYELLOW)
{ SetAPen(rp,CBLACK);
}
else
{ SetAPen(rp,CYELLOW);
}
WritePixel(rp,x,y);
}
}
}
for (i=0; i<NUMSNOW; i++)
{ /* Remove curr's image */
if (!firstpass) undraw(curr,rp);
/* compute new position and appearance */
update(curr,width,height,rp);
/* and display it */
draw(curr,rp);
/* can we continue? */
if (!blankcount)
{ blankcount = BLANKDELAY;
flg_end = ContinueBlanking();
ScreenToFront(scr);
if (flg_end != OK)
{ free(flake);
if (collect) free(collect);
if (starx) free(starx);
if (stary) free(stary);
return flg_end;
}
}
else
{ blankcount--;
}
curr++;
}
if (firstpass) firstpass = false;
}
return OK; /* just for the compiler */
}
bool val(bool x)
{ if (x==random)
return RangeRand(2);
else return x;
}
LONG Blank( PrefObject *Prefs )
{
struct Screen *Scr;
struct Window *Wnd;
LONG RetVal;
BIGFLAKES = val(Prefs[PR_BIG].po_Level);
NUMSNOW = Prefs[PR_FLAKE].po_Level;
COLLECT = val(Prefs[PR_COLLECT].po_Level);
SHOWSNOWMEN = val(Prefs[PR_SNMAN].po_Level);
SHOWSTARS = val(Prefs[PR_STARS].po_Level);
SHOWTREES = val(Prefs[PR_TREE].po_Level);
SHOWBG = val(Prefs[PR_BG].po_Level);
NUMOBJ = Prefs[PR_OBJ].po_Level;
if( Scr = OpenScreenTags( NULL, SA_Depth, 4,
SA_Quiet, TRUE, SA_DisplayID, Prefs[PR_MODE].po_ModeID,
SA_Behind, TRUE, SA_Overscan, OSCAN_STANDARD,
TAG_DONE ))
{
SetRGB4(&( Scr->ViewPort ), 0, 0, 0, 0 );
ColorTable = RainbowPalette( Scr, 0L, 1L, 0L );
SetRGB4(&( Scr->ViewPort ), 1, 15, 15, 15 ); /* white */
SetRGB4(&( Scr->ViewPort ), 2, 0, 10, 0 ); /* green */
SetRGB4(&( Scr->ViewPort ), 3, 8, 5, 4 ); /* brown */
SetRGB4(&( Scr->ViewPort ), 4, 15, 15, 8 ); /* yellow */
SetRGB4(&( Scr->ViewPort ), 5, 4, 4, 4 ); /* dark grey */
SetRGB4(&( Scr->ViewPort ), 6, 8, 8, 8 ); /* mid grey */
SetRGB4(&( Scr->ViewPort ), 7, 12, 12, 12 ); /* light grey */
{ int i;
for (i=8; i<16; i++)
{
SetRGB4(&( Scr->ViewPort ), i, i-7, i-7, i-7); /* different gray */
}
}
Wnd = BlankMousePointer( Scr );
do
RetVal = snow( Scr, Scr->Width, Scr->Height );
while( RetVal == OK );
UnblankMousePointer( Wnd );
RainbowPalette( 0L, ColorTable, 1L, 0L );
CloseScreen( Scr );
}
else
RetVal = FAILED;
return RetVal;
}